package com.example.demo.utils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;

/**
 * xml操作类
 */
public class XMLParser
{

    //将从API返回的XML数据映射到Java对象
    @SuppressWarnings("unchecked")
    public static <T> T getObjectFromXML(String xml, Class<T> tClass)
    {
        XStream xStreamForResponseData = new XStream();
        xStreamForResponseData.alias("xml", tClass);
        xStreamForResponseData.ignoreUnknownElements();//暂时忽略掉一些新增的字段
        return (T) xStreamForResponseData.fromXML(xml);
    }

    //流输出
    public static InputStream getStringStream(String sInputString) throws UnsupportedEncodingException
    {
        ByteArrayInputStream tInputStringStream = null;
        if (sInputString != null && !sInputString.trim().equals(""))
        {
            tInputStringStream = new ByteArrayInputStream(sInputString.getBytes("UTF-8"));
        }
        return tInputStringStream;
    }

    //解析xml封装成map
    public static Map<Object, Object> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException
    {
        //这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream is = getStringStream(xmlString);
        Document document = builder.parse(is);

        //获取到document里面的全部结点
        NodeList allNodes = document.getFirstChild().getChildNodes();
        Node node;
        Map<Object, Object> map = new HashMap<Object, Object>();
        int i = 0;
        while (i < allNodes.getLength())
        {
            node = allNodes.item(i);
            if (node instanceof Element)
            {
                map.put(node.getNodeName(), node.getTextContent());
            }
            i++;
        }
        return map;
    }

    //生成xml
    public static String toXML(Object o)
    {
        XStream xStream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
        xStream.autodetectAnnotations(true);
        return xStream.toXML(o);
    }

    //解析xml封装成map
    @SuppressWarnings("unused")
    public static Map<String, String> doXMLParse(String xml) throws XmlPullParserException, IOException
    {
        InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
        Map<String, String> map = null;
        XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
        pullParser.setInput(inputStream, "UTF-8");
        int eventType = pullParser.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT)
        {
            switch (eventType)
            {
                case XmlPullParser.START_DOCUMENT:
                    map = new HashMap<String, String>();
                    break;
                case XmlPullParser.START_TAG:
                    String key = pullParser.getName();
                    if (key.equals("xml")) {
						break;
					}
                    String value = pullParser.nextText();
                    map.put(key, value);
                    break;
                case XmlPullParser.END_TAG:
                    break;
            }
            eventType = pullParser.next();
        }
        return map;
    }

    /**
     * map转成xml
     *
     * @param paraMap
     * @return
     */
    public static String ArrayToXml(SortedMap<Object, Object> paraMap)
    {
        String xml = "<xml>";
        Iterator<Entry<Object, Object>> iter = paraMap.entrySet().iterator();
        while (iter.hasNext())
        {
            Entry<Object, Object> entry = iter.next();
            String key = entry.getKey().toString();
            String val = entry.getValue().toString();
            xml += "<" + key + ">" + val + "</" + key + ">";
        }
        xml += "</xml>";
        return xml;
    }
}